﻿using System;
using System.Collections.Generic;
using Xenta.Entities;
using Xenta.Utils;

namespace Xenta.Operations
{
    #region __General__

    /// <summary>
    /// Represent the map operation base.
    /// </summary>
    /// <typeparam name="TParent">The type of relation holder entity.</typeparam>
    /// <typeparam name="TChild">The type of child entity.</typeparam>
    public abstract class MapOperation<TParent, TChild> : UpdateEntity<TParent>
        where TParent : class, IRelationHolder<TChild>
        where TChild : class, IEntity
    {
        #region Properties

        /// <summary>
        /// Gets or sets the child entity identifier.
        /// </summary>
        public int ChildID
        {
            get;
            set;
        }

        #endregion

        #region Utilities

        protected override void Revise(IUnitOfWork uow, TParent entity)
        {
            base.Revise(uow, entity);
            entity.Map(uow.Execute(new GetEntity<TChild>
            {
                ThrowsException = true,
                EntityID = ChildID
            }).Result);
        }

        #endregion
    }

    /// <summary>
    /// Represent the unmap operation base.
    /// </summary>
    /// <typeparam name="TParent">The type of relation holder entity.</typeparam>
    /// <typeparam name="TChild">The type of child entity.</typeparam>
    public abstract class UnmapOperation<TParent, TChild> : UpdateEntity<TParent>
        where TParent : class, IRelationHolder<TChild>
        where TChild : class, IEntity
    {
        #region Properties

        /// <summary>
        /// Gets or sets the child entity identifier.
        /// </summary>
        public int ChildID
        {
            get;
            set;
        }

        #endregion

        #region Utilities

        protected override void Revise(IUnitOfWork uow, TParent entity)
        {
            base.Revise(uow, entity);
            entity.Unmap(uow.Execute(new GetEntity<TChild>
            {
                ThrowsException = true,
                EntityID = ChildID
            }).Result);
        }

        #endregion
    }

    #endregion

    #region __Bulk__

    /// <summary>
    /// Represent the map/unmap operation base.
    /// </summary>
    /// <typeparam name="TParent">The type of relation holder entity.</typeparam>
    /// <typeparam name="TChild">The type of child entity.</typeparam>
    public abstract class MapUnmapOperation<TParent, TChild> : UpdateEntity<TParent>
        where TParent : class, IRelationHolder<TChild>
        where TChild : class, IEntity
    {
        #region Properties

        /// <summary>
        /// Gets or sets a collection of the child 
        /// entity identifiers to map/unmpa.
        /// </summary>
        public IDictionary<Int32, Boolean> ChildIDs
        {
            get;
            set;
        }

        #endregion

        #region Utilities

        protected override void Revise(IUnitOfWork uow, TParent entity)
        {
            base.Revise(uow, entity);
            foreach(var kv in ChildIDs)
            {
                if(kv.Value)
                {
                    entity.Map(uow.Execute(new GetEntity<TChild>
                    {
                        ThrowsException = true,
                        EntityID = kv.Key
                    }).Result);
                }
                else
                {
                    entity.Unmap(uow.Execute(new GetEntity<TChild>
                    {
                        ThrowsException = true,
                        EntityID = kv.Key
                    }).Result);
                }
            }
        }

        #endregion
    }

    #endregion
}
